home *** CD-ROM | disk | FTP | other *** search
/ Inside Multimedia 1994 April / Inside Multimedia CD-ROM (April 1994).iso / prg / gs / gssource.exe / GXCLIST.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-24  |  38.0 KB  |  1,220 lines

  1. /* Copyright (C) 1991, 1992 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gxclist.c */
  21. /* Command list 'device' for Ghostscript. */
  22. #include "memory_.h"
  23. #include "gx.h"
  24. #include "gserrors.h"
  25. #include "gxdevice.h"
  26. #include "gxdevmem.h"            /* must precede gxclist.h */
  27. #include "gxclist.h"
  28.  
  29. /* Patch a couple of things possibly missing from stdio.h. */
  30. #ifndef SEEK_SET
  31. #  define SEEK_SET 0
  32. #endif
  33. #ifndef SEEK_END
  34. #  define SEEK_END 2
  35. #endif
  36.  
  37. #define cdev ((gx_device_clist *)dev)
  38.  
  39. /* Forward declarations of procedures */
  40. private dev_proc_open_device(clist_open);
  41. private dev_proc_get_initial_matrix(clist_get_initial_matrix);
  42. private dev_proc_output_page(clist_output_page);
  43. private dev_proc_map_rgb_color(clist_map_rgb_color);
  44. private dev_proc_map_color_rgb(clist_map_color_rgb);
  45. private dev_proc_fill_rectangle(clist_fill_rectangle);
  46. private dev_proc_tile_rectangle(clist_tile_rectangle);
  47. private dev_proc_copy_mono(clist_copy_mono);
  48. private dev_proc_copy_color(clist_copy_color);
  49. private dev_proc_get_bits(clist_get_bits);
  50. private dev_proc_get_props(clist_get_props);
  51. private dev_proc_put_props(clist_put_props);
  52.  
  53. /* The device descriptor */
  54. private gx_device_procs clist_procs =
  55. {    clist_open,
  56.     clist_get_initial_matrix,
  57.     gx_default_sync_output,
  58.     clist_output_page,
  59.     gx_default_close_device,
  60.     clist_map_rgb_color,
  61.     clist_map_color_rgb,
  62.     clist_fill_rectangle,
  63.     clist_tile_rectangle,
  64.     clist_copy_mono,
  65.     clist_copy_color,
  66.     gx_default_draw_line,
  67.     clist_get_bits,
  68.     clist_get_props,
  69.     clist_put_props
  70. };
  71. gx_device_clist gs_clist_device =
  72. {    sizeof(gx_device_clist),
  73.     &clist_procs,
  74.     "command list",
  75.     0, 0, 1, 1, no_margins, dci_black_and_white, 0,    /* generic */
  76.     NULL, NULL, 0
  77. };
  78.  
  79. /* ------ Define the command set and syntax ------ */
  80.  
  81. /* A command always consists of an operation followed by operands. */
  82. /* The operands are implicit in the procedural code. */
  83. typedef enum {
  84.     cmd_op_misc = 0x00,        /* (see below) */
  85.       cmd_opv_end_run = 0x00,    /* (nothing) */
  86.       cmd_opv_set_tile_size = 0x01,    /* width, height */
  87.       cmd_opv_set_tile_phase = 0x02, /* x, y */
  88.     cmd_op_set_color0 = 0x10,    /* color+2 in op byte, [color] */
  89.     cmd_op_set_color1 = 0x20,    /* color+2 in op byte, [color] */
  90.     cmd_op_set_tile_index = 0x30,    /* index */
  91.     cmd_op_fill_rect = 0x40,    /* rect */
  92.     cmd_op_fill_rect_short = 0x50,    /* dh in op byte,dx,dw | rect_short */
  93.     cmd_op_fill_rect_tiny = 0x60,    /* dw in op byte, rect_tiny */
  94.     cmd_op_tile_rect = 0x70,    /* rect */
  95.     cmd_op_tile_rect_short = 0x80,    /* dh in op byte,dx,dw | rect_short */
  96.     cmd_op_tile_rect_tiny = 0x90,    /* dw in op byte, rect_tiny */
  97.     cmd_op_copy_mono = 0xa0,    /* rect, data_x, raster | */
  98.                     /* d_x+1 in op byte, x, y, w, h */
  99.     cmd_op_copy_color = 0xb0,    /* rect, data_x, raster */
  100.     cmd_op_set_tile_bits = 0xc0,    /* index, <bits> */
  101.     cmd_op_delta_tile_bits = 0xd0,    /* n-1 in op byte, n x <offset, bits> */
  102.     cmd_op_end
  103. } gx_cmd_op;
  104. /* Define the size of the largest command, */
  105. /* not counting any bitmap. */
  106. #define w sizeof(short)            /* size of coordinate */
  107. #define d 3                /* size of tile delta */
  108. private uint cmd_largest_size =
  109.   max(1 + 6 * sizeof(short) /* copy_mono */, 2 + 16 * d /* delta_tile 15 */);
  110. #undef d
  111. #undef w
  112. #ifdef DEBUG
  113. private char *cmd_op_names[16] = {
  114.   "misc", "set_color_0", "set_color_1", "set_tile",
  115.   "fill_rect", "fill_rect_short", "fill_rect_tiny", "tile_rect",
  116.   "tile_rect_short", "tile_rect_tiny", "copy_mono", "copy_color",
  117.   "set_tile_bits", "delta_tile_bits", "?e0?", "?f0?"
  118. };
  119. private char *cmd_misc_op_names[16] = {
  120.   "end_run", "set_tile_size", "set_tile_phase", "?03?",
  121.   "?04?", "?05?", "?06?", "?07?",
  122.   "?08?", "?09?", "?0a?", "?0b?",
  123.   "?0c?", "?0d?", "?0e?", "?0f?"
  124. };
  125. private ulong cmd_op_counts[256];
  126. private ulong cmd_tile_count, cmd_copy_count, cmd_delta_tile_count;
  127. private ulong cmd_tile_reset, cmd_tile_found, cmd_tile_added;
  128. private int
  129. count_op(int op)
  130. {    ++cmd_op_counts[op];
  131.     if_debug2('L', ", %s %d\n", cmd_op_names[op >> 4], op & 0xf),
  132.     fflush(dstderr);
  133.     return op;
  134. }
  135. #  define count_add(v, n) (v += (n))
  136. #else
  137. #  define count_op(store_op) store_op
  138. #  define count_add(v, n) 0
  139. #endif
  140. #define count_add1(v) count_add(v, 1)
  141.  
  142. typedef struct {
  143.     short x, y, width, height;
  144. } gx_cmd_rect;
  145. typedef struct {
  146.     byte dx, dwidth, dy, dheight;    /* dy and dheight are optional */
  147. } gx_cmd_rect_short;
  148. #define cmd_min_short (-128)
  149. #define cmd_max_short 127
  150. typedef struct {
  151.     unsigned dx : 4;
  152.     unsigned dy : 4;
  153. } gx_cmd_rect_tiny;
  154. #define cmd_min_tiny (-8)
  155. #define cmd_max_tiny 7
  156.  
  157. /* Define the prefix on each command run in the writing buffer. */
  158. typedef struct cmd_prefix_s cmd_prefix;
  159. struct cmd_prefix_s {
  160.     cmd_prefix *next;
  161.     uint size;
  162. };
  163.  
  164. /* Define the entries in the block file. */
  165. typedef struct cmd_block_s {
  166.     int band;
  167.     long pos;            /* starting position in cfile */
  168. } cmd_block;
  169.  
  170. /* Remember the current state of one band when writing or reading. */
  171. struct gx_clist_state_s {
  172.     gx_color_index color0, color1;    /* most recent colors */
  173.     tile_slot *tile;        /* most recent tile */
  174.     gs_int_point tile_phase;    /* most recent tile phase */
  175.     gx_cmd_rect rect;        /* most recent rectangle */
  176.     /* Following are only used when writing */
  177.     cmd_prefix *head, *tail;    /* list of commands for band */
  178. };
  179. private tile_slot no_tile = { ~0L };
  180.  
  181. /* The initial values for a band state */
  182. private gx_clist_state cls_initial =
  183.    {    gx_no_color_index, gx_no_color_index, &no_tile,
  184.      { 0, 0 }, { 0, 0, 0, 0 },
  185.     0, 0
  186.    };
  187.  
  188. /* Define the size of the command buffer used for reading. */
  189. /* This is needed to split up very large copy_ operations. */
  190. #define cbuf_size 500
  191.  
  192. /* Initialize the device state */
  193. private void clist_init_tiles(P1(gx_device_clist *));
  194. private int
  195. clist_open(gx_device *dev)
  196. {    /*
  197.      * The buffer area (data, data_size) holds a tile cache and a
  198.      * set of block range bit masks when both writing and reading.
  199.      * The rest of the space is used for
  200.      * the command buffer and band state bookkeeping when writing,
  201.      * and for the rendering buffer (image device) when reading.
  202.      * For the moment, we divide the space up arbitrarily.
  203.      *
  204.      * This routine requires only data, data_size, target, and mdev
  205.      * to have been set in the device structure, and is idempotent,
  206.      * so it can be used to check whether a given-size buffer
  207.      * is large enough.
  208.      */
  209.     byte *data = cdev->data;
  210.     uint size = cdev->data_size;
  211. #define alloc_data(n) data += (n), size -= (n)
  212.     gx_device *target = cdev->target;
  213.     int raster, nbands, band;
  214.     gx_clist_state *states;
  215.     uint state_size;
  216.     cdev->ymin = cdev->ymax = -1;    /* render_init not done yet */
  217.     cdev->tile_data = data;
  218.     cdev->tile_data_size = (size / 5) & -4;    /* arbitrary! */
  219.     alloc_data(cdev->tile_data_size);
  220.     raster = ((((ulong)(target->width) * target->color_info.depth + 31) >> 5) << 2) + sizeof(byte *);
  221.     cdev->band_height = size / (uint)raster;
  222.     if ( cdev->band_height == 0 )    /* can't even fit one scan line */
  223.         return_error(gs_error_limitcheck);
  224.     nbands = target->height / cdev->band_height + 1;
  225.     cdev->nbands = nbands;
  226.     if_debug4('l', "[l]width=%d, raster=%d, band_height=%d, nbands=%d\n",
  227.              target->width, raster, cdev->band_height, cdev->nbands);
  228.     state_size = nbands * sizeof(gx_clist_state);
  229.     if ( state_size > size - (sizeof(cmd_prefix) + cmd_largest_size + raster + 4) )        /* not enough room */
  230.         return_error(gs_error_limitcheck);
  231.     cdev->mdev.base = data;
  232.     cdev->states = states = (gx_clist_state *)data;
  233.     alloc_data(state_size);
  234.     cdev->cbuf = data;
  235.     cdev->cnext = data;
  236.     cdev->cend = data + size;
  237.     cdev->ccls = 0;
  238.     for ( band = 0; band < nbands; band++, states++ )
  239.       *states = cls_initial;
  240. #undef alloc_data
  241.     cdev->tile_band_mask_size = (nbands + 31) / 32 * 4;
  242.     cdev->tile_max_size = cdev->tile_data_size -
  243.         (sizeof(tile_hash) * 2 + sizeof(tile_slot) +
  244.          cdev->tile_band_mask_size);
  245.     clist_init_tiles(cdev);
  246.     return 0;
  247. }
  248.  
  249. /* (Re)initialize the tile cache. */
  250. private void
  251. clist_init_tiles(register gx_device_clist *cldev)
  252. {    gx_clist_state *pcls;
  253.     int i, hc;
  254.     cldev->tile_slot_size =
  255.       sizeof(tile_slot) + cldev->tile_band_mask_size +
  256.       cldev->tile.raster * cldev->tile.size.y;
  257.     cldev->tile_max_count = cldev->tile_data_size /
  258.       (sizeof(tile_hash) * 3 /*(worst case)*/ + cldev->tile_slot_size);
  259.     hc = (cldev->tile_max_count - 1) * 2;
  260.     while ( (hc + 1) & hc ) hc |= hc >> 1;    /* make mask */
  261.     if ( hc >= cldev->tile_max_count * 3 ) hc >>= 1;
  262.     if ( hc > 255 )        /* slot index in set_tile is only 1 byte */
  263.        {    hc = 255;
  264.         if ( cldev->tile_max_count > 200 )
  265.             cldev->tile_max_count = 200;
  266.        }
  267.     cldev->tile_hash_mask = hc;
  268.     hc++;                /* make actual size */
  269.     if_debug5('l', "[l]tile.size=%dx%d, slot_size=%d, max_count=%d, hc=%d\n",
  270.          cldev->tile.size.x, cldev->tile.size.y,
  271.          cldev->tile_slot_size, cldev->tile_max_count, hc);
  272.     cldev->tile_hash_table =
  273.         (tile_hash *)(cldev->tile_data + cldev->tile_data_size) - hc;
  274.     cldev->tile_count = 0;
  275.     memset(cldev->tile_data, 0, cldev->tile_data_size);
  276.     memset(cldev->tile_hash_table, -1, hc * sizeof(tile_hash));
  277.     for ( i = 0, pcls = cldev->states; i < cldev->nbands; i++, pcls++ )
  278.         pcls->tile = &no_tile;
  279.     count_add1(cmd_tile_reset);
  280. }
  281.  
  282. /* Forward the non-displaying operations to the target device. */
  283. private void
  284. clist_get_initial_matrix(gx_device *dev, gs_matrix *pmat)
  285. {    (*cdev->target->procs->get_initial_matrix)(dev, pmat);
  286. }
  287. private gx_color_index
  288. clist_map_rgb_color(gx_device *dev, gx_color_value red, gx_color_value green,
  289.   gx_color_value blue)
  290. {    return (*cdev->target->procs->map_rgb_color)(dev, red, green, blue);
  291. }
  292. private int
  293. clist_map_color_rgb(gx_device *dev, gx_color_index color,
  294.   gx_color_value rgb[3])
  295. {    return (*cdev->target->procs->map_color_rgb)(dev, color, rgb);
  296. }
  297. private int
  298. clist_get_props(gx_device *dev, gs_prop_item *plist)
  299. {    gx_device *tdev = cdev->target;
  300.     return (*tdev->procs->get_props)(tdev, plist);
  301. }
  302. private int
  303. clist_put_props(gx_device *dev, gs_prop_item *plist, int count)
  304. {    gx_device *tdev = cdev->target;
  305.     return (*tdev->procs->put_props)(tdev, plist, count);
  306. }
  307.  
  308. /* Print a bitmap for tracing */
  309. #ifdef DEBUG
  310. private void
  311. cmd_print_bits(const byte *data, int height, int raster)
  312. {    int i, j;
  313.     for ( i = 0; i < height; i++ )
  314.        {    const byte *row = data + i * raster;
  315.         dprintf("[L]");
  316.         for ( j = 0; j < raster; j++ )
  317.           dprintf1(" %02x", row[j]);
  318.         dputc('\n');
  319.        }
  320. }
  321. #else
  322. #  define cmd_print_bits(data, height, raster)
  323. #endif
  324.  
  325. /* ------ Writing ------ */
  326.  
  327. /* Utilities */
  328.  
  329. #define cmd_set_rect(rect)\
  330.   ((rect).x = x, (rect).y = y,\
  331.    (rect).width = width, (rect).height = height)
  332.  
  333. #define clist_write(f, str, len)\
  334.   fwrite(str, 1, len, f)
  335.  
  336. /* Write out the buffered commands, and reset the buffer. */
  337. private void
  338. cmd_write_buffer(gx_device_clist *cldev)
  339. {    FILE *cfile = cldev->cfile;
  340.     FILE *bfile = cldev->bfile;
  341.     int nbands = cldev->nbands;
  342.     gx_clist_state *pcls;
  343.     int band;
  344.     for ( band = 0, pcls = cldev->states; band < nbands; band++, pcls++ )
  345.        {    const cmd_prefix *cp = pcls->head;
  346.         if ( cp != 0 )
  347.            {    cmd_block cb;
  348.             cb.band = band;
  349.             cb.pos = ftell(cfile);
  350.             if_debug2('l', "[l]writing for band %d at %ld\n",
  351.                   band, cb.pos);
  352.             clist_write(bfile, (const byte *)&cb, sizeof(cb));
  353.             for ( ; cp != 0; cp = cp->next )
  354.               clist_write(cfile, (const byte *)(cp + 1), cp->size);
  355.             pcls->head = pcls->tail = 0;
  356.             fputc(cmd_opv_end_run, cfile);
  357.            }
  358.        }
  359.     cldev->cnext = cldev->cbuf;
  360.     cldev->ccls = 0;
  361. }
  362.  
  363. /* Add a command to the appropriate band list, */
  364. /* and allocate space for its data. */
  365. /* Return the pointer to the data area. */
  366. private byte *
  367. cmd_put_op(gx_device_clist *cldev, gx_clist_state *pcls, uint size)
  368. {    byte *dp = cldev->cnext;
  369.     if_debug3('L', "[L]band %d: size=%u, left=%d",
  370.           (int)(pcls - cldev->states), size, (int)(cldev->cend - dp));
  371.     if ( size + (sizeof(cmd_prefix) + 4) > cldev->cend - dp )
  372.       { cmd_write_buffer(cldev);
  373.         return cmd_put_op(cldev, pcls, size);
  374.       }
  375.     if ( cldev->ccls == pcls )
  376.       { /* We're adding another command for the same band. */
  377.         /* Tack it onto the end of the previous one. */
  378.         pcls->tail->size += size;
  379.       }
  380.     else
  381.       { cmd_prefix *cp = (cmd_prefix *)(dp + (((byte *)0 - dp) & 3));
  382.         dp = (byte *)(cp + 1);
  383.         if ( pcls->tail != 0 ) pcls->tail->next = cp;
  384.         else pcls->head = cp;
  385.         pcls->tail = cp;
  386.         cldev->ccls = pcls;
  387.         cp->next = 0;
  388.         cp->size = size;
  389.       }
  390.     cldev->cnext = dp + size;
  391.     return dp;
  392. }
  393.  
  394. /* We store all short quantities little-endian. */
  395. /* This is OK, because we read them back little-endian explicitly. */
  396. #define cmd_putw(w, dp)\
  397.   (*dp = (w) & 0xff, dp[1] = (w) >> 8, dp += 2)
  398.  
  399. /* Write a short bitmap.  1 <= bwidth <= 3. */
  400. private void
  401. cmd_put_short_bits(register byte *dp, register const byte *data,
  402.   int raster, register int bwidth, register int height)
  403. {    while ( --height >= 0 )
  404.        {    switch ( bwidth )
  405.            {
  406.         case 3: dp[2] = data[2];
  407.         case 2: dp[1] = data[1];
  408.         case 1: dp[0] = data[0];
  409.            }
  410.         dp += bwidth, data += raster;
  411.        }
  412. }
  413.  
  414. private int
  415. cmd_write_rect_cmd(gx_device *dev, gx_clist_state *pcls,
  416.   int op, int x, int y, int width, int height)
  417. {    int dx = x - pcls->rect.x;
  418.     int dy = y - pcls->rect.y;
  419.     int dwidth = width - pcls->rect.width;
  420.     int dheight = height - pcls->rect.height;
  421. #define check_ranges_1()\
  422.   ((unsigned)(dx - rmin) <= (rmax - rmin) &&\
  423.    (unsigned)(dy - rmin) <= (rmax - rmin) &&\
  424.    (unsigned)(dwidth - rmin) <= (rmax - rmin))
  425. #define check_ranges()\
  426.   (check_ranges_1() &&\
  427.    (unsigned)(dheight - rmin) <= (rmax - rmin))
  428. #define rmin cmd_min_tiny
  429. #define rmax cmd_max_tiny
  430.     cmd_set_rect(pcls->rect);
  431.     if ( dheight == 0 && check_ranges_1() )
  432.        {    byte *dp = cmd_put_op(cdev, pcls, 2);
  433.         count_op(*dp = op + 0x20 + dwidth - rmin);
  434.         dp[1] = (dx << 4) + dy - (rmin * 0x11);
  435.        }
  436. #undef rmin
  437. #undef rmax
  438. #define rmin cmd_min_short
  439. #define rmax cmd_max_short
  440.     else if ( check_ranges() )
  441.        {    int dh = dheight - cmd_min_tiny;
  442.         byte *dp;
  443.         if ( (unsigned)dh <= cmd_max_tiny - cmd_min_tiny && dh != 0 &&
  444.              dy == 0
  445.            )
  446.            {    op += dh;
  447.             dp = cmd_put_op(cdev, pcls, 3);
  448.            }
  449.         else
  450.            {    dp = cmd_put_op(cdev, pcls, 5);
  451.             dp[3] = dy - rmin;
  452.             dp[4] = dheight - rmin;
  453.            }
  454.         count_op(*dp = op + 0x10);
  455.         dp[1] = dx - rmin;
  456.         dp[2] = dwidth - rmin;
  457.        }
  458.     else
  459.        {    byte *dp = cmd_put_op(cdev, pcls, 1 + sizeof(pcls->rect));
  460.         count_op(*dp = op);
  461.         memcpy(dp + 1, &pcls->rect, sizeof(pcls->rect));
  462.        }
  463.     return 0;
  464. }
  465.  
  466. private void
  467. cmd_put_color(gx_device *dev, gx_clist_state *pcls,
  468.   int op, gx_color_index color)
  469. {    if ( (long)color >= -1 && (long)color <= 13 )
  470.         count_op(*cmd_put_op(cdev, pcls, 1) = op + (int)color + 2);
  471.     else
  472.        {    byte *dp = cmd_put_op(cdev, pcls, 1 + sizeof(color));
  473.         count_op(*dp = op);
  474.         memcpy(dp + 1, &color, sizeof(color));
  475.        }
  476. }
  477. private void
  478. cmd_set_colors(gx_device *dev, gx_clist_state *pcls,
  479.   gx_color_index color0, gx_color_index color1)
  480. {    if ( color0 != pcls->color0 )
  481.        {    cmd_put_color(dev, pcls, cmd_op_set_color0, color0);
  482.         pcls->color0 = color0;
  483.        }
  484.     if ( color1 != pcls->color1 )
  485.        {    cmd_put_color(dev, pcls, cmd_op_set_color1, color1);
  486.         pcls->color1 = color1;
  487.        }
  488. }
  489.  
  490. /* Driver interface */
  491.  
  492. /* Macros for dividing up a single call into bands */
  493. #define BEGIN_RECT\
  494.    {    int yend = y + height;\
  495.     int band_height = cdev->band_height;\
  496.     do\
  497.        {    int band = y / band_height;\
  498.         gx_clist_state *pcls = cdev->states + band;\
  499.         height = band_height - y % band_height;\
  500.         if ( yend - y < height ) height = yend - y;\
  501.            {
  502. #define END_RECT\
  503.            }\
  504.         y += height;\
  505.        }\
  506.     while ( y < yend );\
  507.    }
  508.  
  509. private int
  510. clist_fill_rectangle(gx_device *dev, int x, int y, int width, int height,
  511.   gx_color_index color)
  512. {    BEGIN_RECT
  513.     if ( color != pcls->color1 )
  514.         cmd_set_colors(dev, pcls, pcls->color0, color);
  515.     cmd_write_rect_cmd(dev, pcls, cmd_op_fill_rect, x, y, width, height);
  516.     END_RECT
  517.     return 0;
  518. }
  519.  
  520. /* Compare unequal tiles.  Return -1 if unrelated, */
  521. /* or 2<=N<=50 for the size of the delta encoding. */
  522. private int
  523. tile_diff(const byte *old_data, const byte *new_data, uint tsize,
  524.   byte _ss *delta)
  525. {    register const ushort *old2, *new2;
  526.     register ushort diff;
  527.     int count;
  528.     register int i;
  529.     byte _ss *pd;
  530.     if ( tsize > 128 ) return -1;
  531.     old2 = (const ushort *)old_data;
  532.     new2 = (const ushort *)new_data;
  533.     count = 0;
  534.     pd = delta + 2;            /* skip slot index */
  535.     for ( i = 0; i < tsize; i += 2, old2++, new2++ )
  536.       if ( (diff = *new2 ^ *old2) != 0 )
  537. #if arch_is_big_endian
  538. #  define i_hi 0
  539. #  define b_0(w) ((w) >> 8)
  540. #  define b_1(w) ((byte)(w))
  541. #else
  542. #  define i_hi 1
  543. #  define b_0(w) ((byte)(w))
  544. #  define b_1(w) ((w) >> 8)
  545. #endif
  546.        {    if ( count == 16 ) return -1;
  547.         if ( diff & 0xff00 )
  548.            {    if ( diff & 0xff )
  549.                 *pd++ = 0x80 + i,
  550.                 *pd++ = b_0(diff),
  551.                 *pd++ = b_1(diff);
  552.             else
  553.                 *pd++ = i + i_hi, *pd++ = diff >> 8;
  554.            }
  555.         else            /* know diff != 0 */
  556.             *pd++ = i + (1 - i_hi), *pd++ = (byte)diff;
  557.         count++;
  558.        }
  559. #undef b_0
  560. #undef b_1
  561. #undef i_hi
  562.     if ( count == 0 )
  563.     {    /* Tiles are identical.  This is highly unusual, */
  564.         /* but not impossible. */
  565.         pd[0] = pd[1] = 0;
  566.         pd += 2;
  567.         count = 1;
  568.     }
  569.     delta[0] = (byte)cmd_op_delta_tile_bits + count - 1;
  570.     return pd - delta;
  571. }
  572.  
  573. /* Handle changing tiles for clist_tile_rectangle. */
  574. /* We put this in a separate routine, even though it is called only once, */
  575. /* to avoid cluttering up the main-line case of tile_rectangle. */
  576. private int
  577. clist_change_tile(gx_device_clist *cldev, gx_clist_state *pcls,
  578.   const gx_bitmap *tile)
  579. {    uint tile_size = tile->raster * tile->size.y;
  580.     tile_slot *old_tile, *new_tile;
  581.     int slot_index;
  582.     /* Look up the tile in the cache. */
  583. top:       {    gx_bitmap_id id = tile->id;
  584.         uint probe = (uint)(id >> 16) + (uint)(id);
  585.         old_tile = pcls->tile;
  586.         for ( ; ; probe += 25 /* semi-random odd # */ )
  587.            {    tile_hash *hptr = cldev->tile_hash_table +
  588.               (probe & cldev->tile_hash_mask);
  589.             if ( (slot_index = hptr->slot_index) < 0 ) /* empty entry */
  590.                {    /* Must change tiles.  Check whether the */
  591.                 /* tile size has changed. */
  592.                 if ( tile->size.x != cldev->tile.size.x ||
  593.                      tile->size.y != cldev->tile.size.y
  594.                    )
  595.                    {    if ( tile->raster !=
  596.                          ((tile->size.x + 31) >> 5) << 2 ||
  597.                          tile_size > cldev->tile_max_size
  598.                        )
  599.                         return -1;
  600.                     cldev->tile = *tile;    /* reset size, raster */
  601.                     clist_init_tiles(cldev);
  602.                     goto top;
  603.                    }
  604.                 if ( cldev->tile_count == cldev->tile_max_count )
  605.                    {    /* Punt. */
  606.                     clist_init_tiles(cldev);
  607.                     goto top;
  608.                    }
  609.                 hptr->slot_index = slot_index =
  610.                   cldev->tile_count++;
  611.                 new_tile = tile_slot_ptr(cldev, slot_index);
  612.                 new_tile->id = id;
  613.                 memcpy(ts_bits(cldev, new_tile), tile->data, tile_size);
  614.                 count_add1(cmd_tile_added);
  615.                 if_debug3('L', "[L]adding tile %d, hash=%d, id=%lx\n",
  616.                      slot_index,
  617.                      (int)(hptr - cldev->tile_hash_table),
  618.                      id);
  619.                 break;
  620.                }
  621.             new_tile = tile_slot_ptr(cldev, slot_index);
  622.             if ( new_tile->id == id )
  623.                {    count_add1(cmd_tile_found);
  624.                 if_debug1('L', "[L]found tile %d\n",
  625.                       slot_index);
  626.                 break;
  627.                }
  628.            }
  629.        }
  630.     /* Check whether this band knows about this tile yet. */
  631.        {    int band_index = pcls - cldev->states;
  632.         byte pmask = 1 << (band_index & 7);
  633.         byte *ppresent = ts_mask(new_tile) + (band_index >> 3);
  634.         if ( *ppresent & pmask )
  635.            {    /* Tile is known, just put out the index. */
  636.             byte *dp = cmd_put_op(cldev, pcls, 2);
  637.             count_op(*dp = cmd_op_set_tile_index);
  638.             dp[1] = slot_index;
  639.            }
  640.         else
  641.            {    /* Tile is not known, put out the bits.  Use a */
  642.             /* delta encoding or a short encoding if possible. */
  643.             byte *new_data = ts_bits(cldev, new_tile);
  644.             byte *dp;
  645.             byte delta[2+16*3];
  646.             int diff;
  647.             *ppresent |= pmask;
  648.             if ( old_tile != &no_tile &&
  649.                  (diff = tile_diff(ts_bits(cldev, old_tile), new_data, tile_size, delta)) >= 0
  650.                )
  651.                {    /* Use delta representation */
  652.                 dp = cmd_put_op(cldev, pcls, diff);
  653.                 count_op(delta[0]);
  654.                 delta[1] = slot_index;
  655.                 memcpy(dp, delta, diff);
  656.                 count_add(cmd_delta_tile_count, diff - 2);
  657.                }
  658.             else
  659.                {    if ( old_tile == &no_tile )
  660.                    {    byte *dp = cmd_put_op(cldev, pcls,
  661.                         1 + sizeof(cldev->tile.size));
  662.                     count_op(*dp = (byte)cmd_opv_set_tile_size);
  663.                     memcpy(dp + 1, &cldev->tile.size,
  664.                            sizeof(cldev->tile.size));
  665.                    }
  666.                 if ( tile->size.x <= 16 )
  667.                    {    dp = cmd_put_op(cldev, pcls, 2 + (tile_size >> 1));
  668.                     cmd_put_short_bits(dp + 2, new_data, tile->raster, 2, tile->size.y);
  669.                     count_add(cmd_tile_count, tile_size >> 1);
  670.                    }
  671.                 else
  672.                    {    dp = cmd_put_op(cldev, pcls, 2 + tile_size);
  673.                     memcpy(dp + 2, new_data, tile_size);
  674.                     count_add(cmd_tile_count, tile_size);
  675.                    }
  676.                 count_op(*dp = (byte)cmd_op_set_tile_bits);
  677.                 dp[1] = slot_index;
  678.                }
  679.            }
  680.        }
  681.     pcls->tile = new_tile;
  682.     return 0;
  683. }
  684. private int
  685. clist_tile_rectangle(gx_device *dev, const gx_bitmap *tile, int x, int y,
  686.   int width, int height, gx_color_index color0, gx_color_index color1,
  687.   int px, int py)
  688. {    BEGIN_RECT
  689.     if ( tile->id != pcls->tile->id )
  690.        {    if ( clist_change_tile(cdev, pcls, tile) < 0 )
  691.             return gx_default_tile_rectangle(dev, tile, x, y, width, height, color0, color1, px, py);
  692.        }
  693.     if ( color0 != pcls->color0 || color1 != pcls->color1 )
  694.         cmd_set_colors(dev, pcls, color0, color1);
  695.     if ( px != pcls->tile_phase.x || py != pcls->tile_phase.y )
  696.        {    byte *dp = cmd_put_op(cdev, pcls, 1 + sizeof(pcls->tile_phase));
  697.         count_op(*dp = (byte)cmd_opv_set_tile_phase);
  698.         pcls->tile_phase.x = px;
  699.         pcls->tile_phase.y = py;
  700.         memcpy(dp + 1, &pcls->tile_phase, sizeof(pcls->tile_phase));
  701.        }
  702.     cmd_write_rect_cmd(dev, pcls, cmd_op_tile_rect, x, y, width, height);
  703.     END_RECT
  704.     return 0;
  705. }
  706.  
  707. private int
  708. clist_copy_mono(gx_device *dev,
  709.     const byte *data, int data_x, int raster, gx_bitmap_id id,
  710.     int x, int y, int width, int height,
  711.     gx_color_index color0, gx_color_index color1)
  712. {    int y0 = y;
  713.     BEGIN_RECT
  714.     gx_cmd_rect rect;
  715.     uint dsize;
  716.     int bwidth;
  717.     const byte *row = data + (y - y0) * raster;
  718.     byte *dp;
  719.     if ( color0 != pcls->color0 || color1 != pcls->color1 )
  720.         cmd_set_colors(dev, pcls, color0, color1);
  721.     cmd_set_rect(rect);
  722.     if ( width >= 2 && (bwidth = (width + (data_x & 7) + 7) >> 3) <= 3 &&
  723.         height <= min(255, (cbuf_size - (1 + 2 * 2 + 2)) / bwidth)
  724.        )
  725.        {    dsize = height * bwidth;
  726.         dp = cmd_put_op(cdev, pcls, 1 + 2 * 2 + 2 + dsize);
  727.         count_op(*dp++ = (byte)cmd_op_copy_mono + (data_x & 7) + 1);
  728.         cmd_putw(x, dp);
  729.         cmd_putw(y, dp);
  730.         *dp++ = width;
  731.         *dp++ = height;
  732.         row += data_x >> 3;
  733.         cmd_put_short_bits(dp, row, raster, bwidth, height);
  734.         pcls->rect = rect;
  735.         count_add(cmd_copy_count, dsize);
  736.        }
  737.     else
  738.        {    dsize = height * raster;
  739.         if ( dsize > cbuf_size )
  740.            {    /* We have to split it into pieces. */
  741.             if ( height > 1 )
  742.                {    int h2 = height >> 1;
  743.                 clist_copy_mono(dev, row, data_x, raster,
  744.                     gx_no_bitmap_id, x, y, width, h2,
  745.                     color0, color1);
  746.                 clist_copy_mono(dev, row + h2 * raster,
  747.                     data_x, raster, gx_no_bitmap_id,
  748.                     x, y + h2, width, height - h2,
  749.                     color0, color1);
  750.                }
  751.             /* Split a single (very long) row. */
  752.                {    int w2 = width >> 1;
  753.                 clist_copy_mono(dev, row, data_x, raster,
  754.                     gx_no_bitmap_id, x, y, w2, 1,
  755.                     color0, color1);
  756.                 clist_copy_mono(dev, row, data_x + w2,
  757.                     raster, gx_no_bitmap_id, x + w2, y,
  758.                     width - w2, 1, color0, color1);
  759.                }
  760.            }
  761.         else
  762.         {    dp = cmd_put_op(cdev, pcls, 1 + sizeof(rect) + 4 + dsize);
  763.             count_op(*dp++ = (byte)cmd_op_copy_mono);
  764.             memcpy(dp, (byte *)&rect, sizeof(rect));
  765.             dp += sizeof(rect);
  766.             cmd_putw(data_x, dp);
  767.             cmd_putw(raster, dp);
  768.             memcpy(dp, row, dsize);
  769.             pcls->rect = rect;
  770.             count_add(cmd_copy_count, dsize);
  771.         }
  772.        }
  773.     END_RECT
  774.     return 0;
  775. }
  776.  
  777. private int
  778. clist_copy_color(gx_device *dev,
  779.     const byte *data, int data_x, int raster, gx_bitmap_id id,
  780.     int x, int y, int width, int height)
  781. {    int y0 = y;
  782.     BEGIN_RECT
  783.     gx_cmd_rect rect;
  784.     uint dsize = height * raster;
  785.     const byte *row = data + (y - y0) * raster;
  786.     byte *dp;
  787.     if ( dsize > cbuf_size )
  788.        {    /* We have to split it into pieces. */
  789.         if ( height > 1 )
  790.            {    int h2 = height >> 1;
  791.             clist_copy_color(dev, row, data_x, raster,
  792.                 gx_no_bitmap_id, x, y, width, h2);
  793.             clist_copy_color(dev, row + h2 * raster, gx_no_bitmap_id,
  794.                 data_x, raster, x, y + h2, width, height - h2);
  795.            }
  796.         else
  797.            {    /* Split a single (very long) row. */
  798.             int w2 = width >> 1;
  799.             clist_copy_color(dev, row, data_x, raster,
  800.                 gx_no_bitmap_id, x, y, w2, 1);
  801.             clist_copy_color(dev, row, data_x + w2,
  802.                 raster, gx_no_bitmap_id, x + w2, y,
  803.                 width - w2, 1);
  804.            }
  805.        }
  806.     else
  807.     {    cmd_set_rect(rect);
  808.         dp = cmd_put_op(cdev, pcls, 1 + sizeof(rect) + 4 + dsize);
  809.         count_op(*dp++ = (byte)cmd_op_copy_color);
  810.         memcpy(dp, (byte *)&rect, sizeof(rect));
  811.         pcls->rect = rect;
  812.         dp += sizeof(rect);
  813.         cmd_putw(data_x, dp);
  814.         cmd_putw(raster, dp);
  815.         memcpy(dp, row, dsize);
  816.         count_add(cmd_copy_count, dsize);
  817.     }
  818.     END_RECT
  819.     return 0;
  820. }
  821.  
  822. /* ------ Reading/rendering ------ */
  823.  
  824. /* Clean up after rendering a page. */
  825. private int
  826. clist_output_page(gx_device *dev, int num_copies, int flush)
  827. {    if ( flush )
  828.        {    rewind(cdev->cfile);
  829.         rewind(cdev->bfile);
  830.         cdev->bfile_end_pos = 0;
  831.        }
  832.     else
  833.        {    fseek(cdev->cfile, 0L, SEEK_END);
  834.         fseek(cdev->bfile, 0L, SEEK_END);
  835.        }
  836.     return clist_open(dev);        /* reinitialize */
  837. }
  838.  
  839. private int clist_render_init(P1(gx_device_clist *));
  840. private int clist_render(P3(gx_device_clist *, gx_device *, int));
  841.  
  842. /* Copy scan lines to the client.  This is where rendering gets done. */
  843. private int
  844. clist_get_bits(gx_device *dev, int start_y,
  845.   byte *str, uint size, int pad_to_word)
  846. {    int y = start_y;
  847.     byte *dest = str;
  848.     gx_device_memory *mdev = &cdev->mdev;
  849.     uint bytes_per_line;
  850.     uint count, left;
  851.     /* Initialize for rendering if we haven't done so yet. */
  852.     if ( cdev->ymin < 0 )
  853.         clist_render_init(cdev);
  854.     bytes_per_line = gx_device_bytes_per_scan_line((gx_device *)mdev,
  855.                                pad_to_word);
  856.     count = min(size / bytes_per_line,
  857.             cdev->target->height - start_y);
  858.     /* Render bands and copy them incrementally. */
  859.     for ( left = count; left; )
  860.        {    int n;
  861.         if ( !(y >= cdev->ymin && y < cdev->ymax) )
  862.            {    int band = y / mdev->height;
  863.             int code;
  864.             rewind(cdev->bfile);
  865.             (*mdev->procs->open_device)((gx_device *)mdev);    /* reinitialize */
  866.             code = clist_render(cdev, (gx_device *)mdev, band);
  867.             if ( code < 0 ) return code;
  868.             cdev->ymin = band * mdev->height;
  869.             cdev->ymax = cdev->ymin + mdev->height;
  870.            }
  871.         n = min(cdev->ymax - y, left);
  872.         (*mdev->procs->get_bits)((gx_device *)mdev,
  873.                      y - cdev->ymin, dest,
  874.                      bytes_per_line * n, pad_to_word);
  875.         y += n, dest += bytes_per_line * n, left -= n;
  876.        }
  877.     return count;
  878. }
  879.  
  880. #undef cdev
  881.  
  882. /* Initialize for reading. */
  883. private int
  884. clist_render_init(gx_device_clist *cdev)
  885. {    gx_device *target = cdev->target;
  886.     byte *base = cdev->mdev.base;    /* save */
  887.     int depth = target->color_info.depth;
  888.     uint raster = ((target->width * depth + 31) >> 5) << 2;
  889.     const gx_device_memory *mdev = gdev_mem_device_for_bits(depth);
  890.     if ( mdev == 0 )
  891.         return_error(gs_error_rangecheck);
  892.     cmd_write_buffer(cdev);        /* flush buffer */
  893.     /* Write the terminating entry in the block file. */
  894.     /* Note that because of copypage, there may be many such entries. */
  895.        {    cmd_block cb;
  896.         cb.band = -1;
  897.         cb.pos = ftell(cdev->cfile);
  898.         clist_write(cdev->bfile, (byte *)&cb, sizeof(cb));
  899.         cdev->bfile_end_pos = ftell(cdev->bfile);
  900.        }
  901.     cdev->mdev = *mdev;
  902.     cdev->mdev.base = base;        /* restore */
  903.     (*target->procs->get_initial_matrix)(target, &cdev->mdev.initial_matrix);
  904.     cdev->mdev.width = target->width;
  905.     cdev->mdev.height = cdev->band_height;
  906.     cdev->mdev.raster = raster;
  907.     cdev->ymin = cdev->ymax = 0;
  908. #ifdef DEBUG
  909. if ( gs_debug['l'] | gs_debug['L'] )
  910.    {    int ci, cj;
  911.     dprintf3("[l]counts: tile = %ld, copy = %ld, delta = %ld\n",
  912.              cmd_tile_count, cmd_copy_count, cmd_delta_tile_count);
  913.     dprintf3("           reset = %ld, found = %ld, added = %ld\n",
  914.              cmd_tile_reset, cmd_tile_found, cmd_tile_added);
  915.     for ( ci = 0; ci < 0x100; ci += 0x10 )
  916.        {    dprintf1("[l]  %s =", cmd_op_names[ci >> 4]);
  917.         for ( cj = ci; cj < ci + 0x10; cj++ )
  918.             dprintf1(" %ld", cmd_op_counts[cj]);
  919.         dputs("\n");
  920.        }
  921.    }
  922. #endif
  923.     return 0;
  924. }
  925.  
  926. /* Render one band to a specified target device. */
  927. #define assign_getw(var, p)\
  928.   (var = *p + ((uint)p[1] << 8), p += 2)
  929. typedef byte _ss *cb_ptr;
  930. private void clist_read(P3(FILE *, byte *, uint));
  931. private cb_ptr clist_read_short_bits(P6(FILE *, byte *, int, int, cb_ptr, cb_ptr));
  932. private int
  933. clist_render(gx_device_clist *cdev, gx_device *tdev, int band)
  934. {    byte cbuf[cbuf_size];
  935.     byte bits[4 * 255];        /* for short copy_mono bits */
  936.     register cb_ptr cbp;
  937.     cb_ptr cb_limit;
  938.     cb_ptr cb_end;
  939.     FILE *file = cdev->cfile;
  940.     FILE *bfile = cdev->bfile;
  941.     int y0 = band * cdev->band_height;
  942.     gx_clist_state state;
  943.     gx_bitmap state_tile;
  944.     uint tile_bits_size;        /* size of bits of each tile */
  945.     gs_int_point tile_phase;
  946.     cmd_block b_this;
  947.     long pos;
  948.     uint left;
  949. #define cmd_read_var(ptr, cbp)\
  950.   memcpy(ptr, cbp, sizeof(*ptr)),\
  951.   cbp += sizeof(*ptr)
  952. #define cmd_read(ptr, vsize, cbp)\
  953.   if ( cb_end - cbp >= vsize )\
  954.     memcpy(ptr, cbp, vsize), cbp += vsize;\
  955.   else\
  956.    { uint cleft = cb_end - cbp;\
  957.      memcpy(ptr, cbp, cleft); vsize -= cleft;\
  958.      clist_read(file, ptr + cleft, vsize);\
  959.      cbp = cb_end;\
  960.    }
  961. #define cmd_read_short_bits(ptr, bw, ht, cbp)\
  962.   cbp = clist_read_short_bits(file, ptr, bw, ht, cbp, cb_end)
  963.     state = cls_initial;
  964.     state_tile.id = 0;
  965.     tile_phase.x = tile_phase.y = 0;
  966. trd:    clist_read(bfile, (byte *)&b_this, sizeof(b_this));
  967. top:    /* Find the next run of commands for this band. */
  968.     if ( b_this.band < 0 && ftell(bfile) == cdev->bfile_end_pos )
  969.         return 0;    /* end of bfile */
  970.     if ( b_this.band != band ) goto trd;
  971.     pos = b_this.pos;
  972.     clist_read(bfile, (byte *)&b_this, sizeof(b_this));
  973.     fseek(file, pos, SEEK_SET);
  974.     left = (uint)(b_this.pos - pos);
  975.     cb_limit = cbuf + (cbuf_size - cmd_largest_size);
  976.     cb_end = cbuf + cbuf_size;
  977.     cbp = cb_end;
  978.     for ( ; ; )
  979.        {    int op;
  980.         uint bytes;
  981.         int data_x, raster;
  982.         int code;
  983.         cb_ptr source;
  984.         gx_color_index _ss *pcolor;
  985.         /* Make sure the buffer contains a full command. */
  986.         if ( cbp > cb_limit )
  987.            {    uint nread;
  988.             memcpy(cbuf, cbp, cb_end - cbp);
  989.             cbp = cbuf + (cb_end - cbp);
  990.             nread = cb_end - cbp;
  991.             if ( nread > left ) nread = left;
  992.             clist_read(file, cbp, nread);
  993.             cb_end = cbp + nread;
  994.             cbp = cbuf;
  995.             left -= nread;
  996.             if ( cb_limit > cb_end ) cb_limit = cb_end;
  997.            }
  998.         op = *cbp++;
  999.         if_debug2('L', "[L]%s %d:\n",
  1000.               cmd_op_names[op >> 4], op & 0xf);
  1001.         switch ( op >> 4 )
  1002.            {
  1003.         case cmd_op_misc >> 4:
  1004.             switch ( op )
  1005.                {
  1006.             case cmd_opv_end_run:
  1007.                 goto top;
  1008.             case cmd_opv_set_tile_size:
  1009.                 cmd_read_var(&state_tile.size, cbp);
  1010.                 state_tile.raster = ((state_tile.size.x + 31) >> 5) << 2;
  1011.                 /* We can't actually know the rep_size, */
  1012.                 /* so we play it safe. */
  1013.                 state_tile.rep_width = state_tile.size.x;
  1014.                 state_tile.rep_height = state_tile.size.y;
  1015.                 cdev->tile_slot_size = tile_bits_size =
  1016.                     state_tile.raster * state_tile.size.y;
  1017.                 break;
  1018.             case cmd_opv_set_tile_phase:
  1019.                 cmd_read_var(&state.tile_phase, cbp);
  1020.                 break;
  1021.             default:
  1022.                 goto bad_op;
  1023.                }
  1024.             tile_phase.x = state.tile_phase.x % state_tile.size.x;
  1025.             tile_phase.y = (state.tile_phase.y + y0) % state_tile.size.y;
  1026.             continue;
  1027.         case cmd_op_set_color0 >> 4:
  1028.             pcolor = &state.color0;
  1029.             goto set_color;
  1030.         case cmd_op_set_color1 >> 4:
  1031.             pcolor = &state.color1;
  1032. set_color:        if ( op & 0xf )
  1033.                 *pcolor = (gx_color_index)(long)((op & 0xf) - 2);
  1034.             else
  1035.                 cmd_read_var(pcolor, cbp);
  1036.             continue;
  1037.         case cmd_op_set_tile_index >> 4:
  1038.             state_tile.data = (byte *)tile_slot_ptr(cdev, *cbp);
  1039.             cbp++;
  1040.             continue;
  1041.         case cmd_op_copy_mono >> 4:
  1042.             if ( op & 0xf )
  1043.                {    assign_getw(state.rect.x, cbp);
  1044.                 assign_getw(state.rect.y, cbp);
  1045.                 state.rect.width = *cbp++;
  1046.                 state.rect.height = *cbp++;
  1047.                 break;
  1048.                }
  1049.             /* falls through */
  1050.         case cmd_op_fill_rect >> 4:
  1051.         case cmd_op_tile_rect >> 4:
  1052.         case cmd_op_copy_color >> 4:
  1053.             cmd_read_var(&state.rect, cbp);
  1054.             break;
  1055.         case cmd_op_fill_rect_short >> 4:
  1056.         case cmd_op_tile_rect_short >> 4:
  1057.             state.rect.x += *cbp + cmd_min_short;
  1058.             state.rect.width += cbp[1] + cmd_min_short;
  1059.             if ( op & 0xf )
  1060.                {    state.rect.height += (op & 0xf) + cmd_min_tiny;
  1061.                 cbp += 2;
  1062.                }
  1063.             else
  1064.                {    state.rect.y += cbp[2] + cmd_min_short;
  1065.                 state.rect.height += cbp[3] + cmd_min_short;
  1066.                 cbp += 4;
  1067.                }
  1068.             break;
  1069.         case cmd_op_fill_rect_tiny >> 4:
  1070.         case cmd_op_tile_rect_tiny >> 4:
  1071.            {    int txy = *cbp++;
  1072.             state.rect.x += (txy >> 4) + cmd_min_tiny;
  1073.             state.rect.y += (txy & 0xf) + cmd_min_tiny;
  1074.             state.rect.width += (op & 0xf) + cmd_min_tiny;
  1075.            }    break;
  1076.         case cmd_op_set_tile_bits >> 4:
  1077.             state_tile.data = (byte *)tile_slot_ptr(cdev, *cbp);
  1078.             cbp++;
  1079.             if ( state_tile.size.x <= 16 )
  1080.                {    cmd_read_short_bits(state_tile.data, 2, state_tile.size.y, cbp);
  1081.                }
  1082.             else
  1083.                {    bytes = tile_bits_size;
  1084.                 cmd_read(state_tile.data, bytes, cbp);
  1085.                }
  1086. #ifdef DEBUG
  1087. if ( gs_debug['L'] )
  1088.             cmd_print_bits(state_tile.data, state_tile.size.y,
  1089.                        state_tile.raster);
  1090. #endif
  1091.             continue;
  1092.         case cmd_op_delta_tile_bits >> 4:
  1093.            {    byte *new_data = (byte *)tile_slot_ptr(cdev, *cbp);
  1094.             cbp++;
  1095.             memcpy(new_data, state_tile.data, tile_bits_size);
  1096.             state_tile.data = new_data;
  1097.             do
  1098.                {    uint offset = *cbp;
  1099.                 if ( offset < 0x80 )
  1100.                     new_data[offset] ^= cbp[1],
  1101.                     cbp += 2;
  1102.                 else
  1103.                     offset -= 0x80,
  1104.                     new_data[offset] ^= cbp[1],
  1105.                     new_data[offset + 1] ^= cbp[2],
  1106.                     cbp += 3;
  1107.                }
  1108.             while ( op-- & 0xf );
  1109.            }    continue;
  1110.         default:
  1111. bad_op:            lprintf5("Bad op %02x band %d file pos %ld buf pos %d/%d\n",
  1112.                  op, band, ftell(file), (int)(cbp - cbuf), (int)(cb_end - cbuf));
  1113.                {    cb_ptr pp;
  1114.                 for ( pp = cbuf; pp < cb_end; pp += 10 )
  1115.                   lprintf10(" %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  1116.                        pp[0], pp[1], pp[2], pp[3], pp[4],
  1117.                        pp[5], pp[6], pp[7], pp[8], pp[9]);
  1118.                }
  1119.             return_error(gs_error_Fatal);
  1120.            }
  1121.         if_debug4('L', "[L]  x=%d y=%d w=%d h=%d\n",
  1122.               state.rect.x, state.rect.y, state.rect.width,
  1123.               state.rect.height);
  1124.         switch ( op >> 4 )
  1125.            {
  1126.         case cmd_op_fill_rect >> 4:
  1127.         case cmd_op_fill_rect_short >> 4:
  1128.         case cmd_op_fill_rect_tiny >> 4:
  1129.             code = (*tdev->procs->fill_rectangle)
  1130.               (tdev, state.rect.x, state.rect.y - y0,
  1131.                state.rect.width, state.rect.height, state.color1);
  1132.             break;
  1133.         case cmd_op_tile_rect >> 4:
  1134.         case cmd_op_tile_rect_short >> 4:
  1135.         case cmd_op_tile_rect_tiny >> 4:
  1136.             code = (*tdev->procs->tile_rectangle)
  1137.               (tdev, &state_tile,
  1138.                state.rect.x, state.rect.y - y0,
  1139.                state.rect.width, state.rect.height,
  1140.                state.color0, state.color1,
  1141.                tile_phase.x, tile_phase.y);
  1142.             break;
  1143.         case cmd_op_copy_mono >> 4:
  1144.             if ( op & 0xf )
  1145.                {    data_x = (op & 0xf) - 1;
  1146.                 raster = 4;
  1147.                 cmd_read_short_bits(bits, (data_x + state.rect.width + 7) >> 3, state.rect.height, cbp);
  1148.                 source = bits;
  1149.                 goto copy;
  1150.                }
  1151.             /* falls through */
  1152.         case cmd_op_copy_color >> 4:
  1153.             assign_getw(data_x, cbp);
  1154.             assign_getw(raster, cbp);
  1155.             bytes = state.rect.height * raster;
  1156.             /* copy_mono and copy_color have ensured that */
  1157.             /* the bits will fit in a single buffer. */
  1158.             cmd_read(cbuf, bytes, cbp);
  1159.             source = cbuf;
  1160. copy:
  1161. #ifdef DEBUG
  1162. if ( gs_debug['L'] )
  1163.    {            dprintf2("[L]  data_x=%d raster=%d\n",
  1164.                  data_x, raster);
  1165.             cmd_print_bits(source, state.rect.height, raster);
  1166.    }
  1167. #endif
  1168.             code = (op >> 4 == (byte)cmd_op_copy_mono >> 4 ?
  1169.               (*tdev->procs->copy_mono)
  1170.                 (tdev, source, data_x, raster, gx_no_bitmap_id,
  1171.                  state.rect.x, state.rect.y - y0,
  1172.                  state.rect.width, state.rect.height,
  1173.                  state.color0, state.color1) :
  1174.               (*tdev->procs->copy_color)
  1175.                 (tdev, source, data_x, raster, gx_no_bitmap_id,
  1176.                  state.rect.x, state.rect.y - y0,
  1177.                  state.rect.width, state.rect.height));
  1178.             break;
  1179.            }
  1180.         if ( code < 0 ) return_error(code);
  1181.        }
  1182. }
  1183. /* The typical implementations of fread and fseek */
  1184. /* are extremely inefficient for small counts, */
  1185. /* so we use loops instead. */
  1186. private void
  1187. clist_read(FILE *f, byte *str, uint len)
  1188. {    switch ( len )
  1189.        {
  1190.     default: fread(str, 1, len, f); break;
  1191.     case 8: *str++ = (byte)getc(f);
  1192.     case 7: *str++ = (byte)getc(f);
  1193.     case 6: *str++ = (byte)getc(f);
  1194.     case 5: *str++ = (byte)getc(f);
  1195.     case 4: *str++ = (byte)getc(f);
  1196.     case 3: *str++ = (byte)getc(f);
  1197.     case 2: *str++ = (byte)getc(f);
  1198.     case 1: *str = (byte)getc(f);
  1199.        }
  1200. }
  1201. /* Read a short bitmap */
  1202. private cb_ptr
  1203. clist_read_short_bits(FILE *file, byte *data, register int bwidth, int height,
  1204.   cb_ptr cbp, cb_ptr cb_end)
  1205. {    uint bytes = bwidth * height;
  1206.     byte *pdata = data + bytes;
  1207.     byte *udata = data + (height << 2);
  1208.     cmd_read(data, bytes, cbp);
  1209.     while ( --height > 0 )        /* first row is in place already */
  1210.        {    udata -= 4, pdata -= bwidth;
  1211.         switch ( bwidth )
  1212.            {
  1213.         case 3: udata[2] = pdata[2];
  1214.         case 2: udata[1] = pdata[1];
  1215.         case 1: udata[0] = pdata[0];
  1216.            }
  1217.        }
  1218.     return cbp;
  1219. }
  1220.